<template>
  <Category :disabled="!isShowList" />
  <el-card
    shadow="always"
    :body-style="{ padding: '20px' }"
    :style="{marginTop: '30px'}"
  >
    <template #header v-if="isShowList">
    <el-button 
    type="primary" 
    size="default"
     @click="addAttr" 
    :icon="Plus"
    :disabled="!category3Id"
    >
      新增属性</el-button>
    </template>
     <!-- card body -->
    <el-table border stripe :data="attrList" v-if="isShowList">
    <el-table-column label="序号" type="index" width="80" />
    <el-table-column 
    label="属性名称" 
    width="150" 
    prop="attrName"
    ></el-table-column>
    <el-table-column label="属性值名称列表" prop="attrValueList">
    <template v-slot="{row}">
    <el-tag 
    type="danger"
    size="default"
    effect="dark"
    v-for="item in row.attrValueList"
    :key="item.id"
    >{{ item.valueName }}</el-tag>
    </template>
    </el-table-column>
    <el-table-column label="操作" width="150">
      <template v-slot="{ row }">
        <el-button
            type="warning"
            size="default"
            @click="editAttr(row)"
            :icon="Edit"
          ></el-button>
          <el-popconfirm
            title="你确定要删除这个属性吗?"
            @confirm="deleteAttr(row)"
          >
            <template #reference>
              <el-button
                type="danger"
                size="default"
                :icon="Delete"
              ></el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>

    <div v-else>
      <el-form label-width="80px" :inline="true">
        <el-form-item label="属性名">
          <el-input
            placeholder="请输入属性名"
            v-model="newAttrData.attrName"
          ></el-input>
        </el-form-item>
      </el-form>
      <div>
        <el-button type="primary" @click="addAttrValue"
        :disabled="!newAttrData.attrName"
        >添加属性值</el-button>
        <el-button type="default" @click="cancle">取消</el-button>
      </div>
      <el-table 
      :data="newAttrData.attrValueList"
      border 
      stripe 
      :style="{ marginTop: '30px' }">
        <el-table-column type="index" width="80" label="序号" />
        <el-table-column label="属性值名称" prop="valueName">
          <template v-slot="{ row,$index }">
            <el-input
              placeholder="请输入新增的属性值名称"
              size="default"
              v-model="row.valueName"
              v-if="row.isEdit"
              @blur="changeToLook(row,$index)"
              ref="editEle"
              @focus="saveOldValue(row)"
            ></el-input>
            <span
              v-else
              @click="changeToEdit(row)"
              :style="{ display: 'inline-block', width: '70%' }"
              >{{ row.valueName }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作">
          <template v-slot="{ $index }">
            <!-- 气泡确认框 -->
            <el-popconfirm
              title="你确定要删除这个属性吗?"
              @confirm="deleteAttrValue($index)"
            >
              <template #reference>
                <el-button
                  type="danger"
                  size="small"
                  icon="ele-Delete"
                ></el-button>
              </template>
            </el-popconfirm>
          </template>

        </el-table-column>
      </el-table>
      <div style="margin-top: 30px">
        <el-button type="primary" @click="saveAttr"
        :disabled="
        newAttrData.attrValueList.length <= 0 || !newAttrData.attrName
        "
        >保存</el-button>
        <el-button type="default" @click="cancle">取消</el-button>
      </div>
    </div>
  </el-card>
</template>
<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "Attr",
});
</script>

<script setup lang="ts">
import { Plus, Edit, Delete } from "@element-plus/icons-vue";
import { watch, ref,nextTick } from "vue";
import useAttrStore from "@/stores/attr";
import { storeToRefs } from "pinia";
import type { attrListType ,attrListItemType, attrValueListType} from "@/api/attr";
import { requestAttrList ,requestUpdateOrAddAttr ,requestDeleteAttr} from "@/api/attr";
import cloneDeep from "lodash/cloneDeep";
import { ElMessage } from "element-plus";


const attrStore =useAttrStore();
const {category3Id,category2Id,category1Id} = storeToRefs(attrStore);

// 存放三级分类得到的属性列表
const attrList =ref<attrListType>([]);
// 监听第三级分类的改变，然后请求属性列表

//封装一个获取属性列表的请求函数
const getAttrList = async () => {
  const result = await requestAttrList(
    category1Id.value as number,
    category2Id.value as number,
    category3Id.value as number
  );

  attrList.value = result;
};
//监听第三级分类的改变,然后请求属性列表
watch(
  category3Id,
  (newValue) => {
    //如果3级列表项变为了null,则把属性列表的数据清空
    if (!newValue) {
      attrList.value = [];
      return;
    }
    //发起属性列表请求
    getAttrList();
  },
  { immediate: true }
);

// 2.添加平台属性逻辑
// 定义一个新增平台属性的一个初始数据，将来新增点击保存的时候，把这个值提交
const newAttrData = ref<attrListItemType>({
  attrName: "",
  categoryId: category3Id.value as number, //固定是category3Id
  categoryLevel: 3, //固定是3
  attrValueList: [],
});
// 数据保存平台属性页是否展示，可以切换到新增或修改页
const isShowList = ref(true);

// 新增平台属性事件函数
const addAttr =() =>{
  // 切换到新增页
  isShowList.value = false;
  // 每次新增的时候，清空上一次可能残留的数据（重新给newAttrData赋一个初始值)）
  newAttrData.value = {
    attrName: "",
    categoryId: category3Id.value as number, //固定是category3Id
    categoryLevel: 3, //固定是3
    attrValueList: [],
  };
};
// 取消新增或者修改的功能及视图
const cancle = () =>{
  // 先切换到属性列表页
  isShowList.value =true;
};

//给新增的属性 添加属性值的事件回调函数
const addAttrValue = () => {
  //创建一个属性值的数据
  const newAttrValue = ref({
    valueName: "", //当前新增属性值的内容(目前为空占位,等视图渲染后,在input中数据双向绑定输入)
    attrId: newAttrData.value.id, //当前属性值所在的属性的id(就算是新增,属性没有id,我们也要关联,将来后端添加id的时候,我就有值了)
    isEdit: true, //我们给新增的属性值数据中添加一个逻辑 isEdit代表当前模式是否是编辑模式(新增的数据肯定是编辑模式)
  });
  //把新增的属性值数据  添加到新属性的  属性值列表的数组中
  newAttrData.value.attrValueList.push(newAttrValue.value);
  nextTick(()=>{
    editEle.value.focus();
  })
};

// 在属性列表中修改某个属性的事件方法
const editAttr = (row:attrListItemType) =>{
  //先切换到新增或者添加属性页
  isShowList.value = false;
  // 回填数据，因为视图和初始新增数据的newAttrData进行深度绑定，所以回填的时候，直接把被修改的数据赋值给newAttrData即可
  const cloneRow = cloneDeep(row);
  cloneRow.attrValueList.forEach((item) =>{
  item.isEdit=false;
});
 //回填数据,因为视图和初始新增数据的newAttrData进行深度绑定,所以回填的时候,直接把被修改的数据赋值给newAttrData即可
 newAttrData.value = cloneRow
};

// 创建一个数据用来保存编辑模式的input元素
const editEle = ref();
  //切换查看模式到编辑模式给span绑定的点击事件回调函数
  const changeToEdit = (row:attrValueListType) =>{
    // row是当前的属性值所在的数据，把当前的数据的isEdit变为true
    row.isEdit = true;
    // 让当前的表单自动获取焦点（操作真实DOM的时候，看情况要放在nextTick中，等DOM加载完成才能执行）
    nextTick(()=>{
      editEle.value.focus();
    });
  };
  // 给它用全局变量写一个旧值为空
  let oldAttrValueName="";
  // 给编辑模式绑定获取焦点事件，保存旧值
  const saveOldValue = (row:attrValueListType) =>{
    //先把当前的旧值保存起来
    oldAttrValueName=row.valueName
    console.log(oldAttrValueName);
    
  }

  // 切换到查看模式的事件回调函数
  const changeToLook = (row: attrValueListType ,$index:number) =>{
    // row是当前属性值所在的数据，把当前的数据中的isEdit变为false
    row.isEdit = false;

    // 判断输入的是否为空
    if(!row.valueName.trim()){
      //如果输入为空，并且旧值也为空，那么说明当前是新增属性值，并且用户没有填，直接删除
      if (!oldAttrValueName) {
        newAttrData.value.attrValueList.splice($index, 1);
      } else {
        // 如果有旧值，则直接把旧值还给用户，并把旧值清空
        row.valueName = oldAttrValueName;
      };
    };

    //判断用户输入的是否有重值选项，如果有，则恢复
    let isRepeat = newAttrData.value.attrValueList.some((item)=>{
      //如果自己比较自己的时候，我们跳过（不跳过的话，永远isRepeat为true）
      if (item === row) {
        return;
      }
      return item.valueName === row.valueName;
    });

    // 判断在数据列表中除了row自身以为，还有没有谁的valueName值和row的相等，如果有，则恢复旧值
    if (isRepeat) {
      if(oldAttrValueName){
      row.valueName = oldAttrValueName;
      }else {
        newAttrData.value.attrValueList.splice($index,1);
      }
    };

    // 统一在失去焦点事件结束的时候，清空旧值
    oldAttrValueName = "";
  };

  // 确认删除某条属性值的回调函数
  const deleteAttrValue = ($index:number) =>{
    newAttrData.value.attrValueList.splice($index,1);
  };

  // 确认保存修改或者新增的属性值列表
  const saveAttr = async ()=>{
    //newAttrDate就是我们发送请求的参数
    // 1.在保存值的时候把isEdit属性删除调掉
    newAttrData.value.attrValueList.forEach((item) => {
      delete item.isEdit;
    });

    //2.判断当前的属性值列表是否为空，如果为空就不提交了
    if (newAttrData.value.attrValueList.length <= 0) {
      ElMessage.error("属性值列表不能为空");
      return;
    }

    //发送请求
    try {
      await requestUpdateOrAddAttr(newAttrData.value);
      ElMessage.success("新增或者修改成功");
      //返回属性列表视图
      isShowList.value =true;
      //重新发送请求
      getAttrList();
    } catch (e) {
      ElMessage.error("新增或者修改失败");
    }
  };

  // 删除某条属性的回调函数
  const deleteAttr = async (row:attrListItemType) =>{
    //发送删除请求
    try {
      await requestDeleteAttr(row.id as number);
      ElMessage.success("删除属性成功");
      // 重新发送请求
      getAttrList();
    }catch(e) {
      ElMessage.error("删除属性失败");
    }
  };

/* 
  拷贝:
    - 注意!!!如果只是简单的地址赋值,那么不能被称作为拷贝!!!!!  比如 obj1 = obj2(只是地址的赋值,没有拷贝这一说)
    - 只要牵扯到拷贝,那么两个对象的地址一定不一样
      - 假设对象内部深层次的也有对象类型,那么如果内部的对象地址一致,则当前的拷贝被作为浅拷贝
      - 那么如果内部所有深层次的对象地址都不一致,则当前的拷贝被作为深拷贝
*/

/* const obj1 = {
  name: "李博",
  hobby: ["吃", "喝"],//0x111
  score: {
    html: 90,
    css: 70,
    vue: 10,
  },
}; */

//不是拷贝,只是地址的赋值,两个对象其实是同一个东西,保存的地址一模一样
// const obj2 = obj1;

//浅拷贝
/* const obj2 = { ...obj1 }; */
</script>

<style>

</style>